from flask import Flask, request, jsonify
from flask_cors import CORS
from dotenv import load_dotenv
import os
from supabase import create_client, Client
import uuid
from datetime import datetime, timedelta
import logging
from openai import OpenAI
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

# 配置日志
logging.basicConfig(level=logging.INFO, 
                   format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# 加载环境变量
load_dotenv()

app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})  # 允许所有来源

# 初始化Supabase客户端
supabase_url = os.getenv("SUPABASE_URL")
supabase_key = os.getenv("SUPABASE_KEY")
logger.info(f"Supabase URL: {supabase_url}")
logger.info(f"Supabase Key: {'设置了' if supabase_key else '未设置'}")

supabase: Client = create_client(supabase_url, supabase_key)

# 初始化OpenAI客户端
client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'), base_url='https://api.siliconflow.cn/v1')

# 初始化限速器
limiter = Limiter(
    key_func=get_remote_address,
    app=app,
    default_limits=["200 per day", "50 per hour"]
)

# 创建笔记本
@app.route('/api/notebooks', methods=['POST'])
@limiter.limit("30 per minute")
def create_notebook():
    data = request.json
    if not data or 'name' not in data:
        return jsonify({"error": "笔记本名称不能为空"}), 400
    
    try:
        notebook_id = str(uuid.uuid4())
        response = supabase.table('notebooks').insert({
            "id": notebook_id,
            "name": data['name'],
            "card_count": 0
        }).execute()
        
        return jsonify(response.data[0]), 201
    except Exception as e:
        logger.error(f"创建笔记本失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 获取笔记本列表
@app.route('/api/notebooks', methods=['GET'])
@limiter.limit("60 per minute")
def get_notebooks():
    try:
        logger.info("获取笔记本列表")
        response = supabase.table('notebooks').select("*").execute()
        logger.info(f"获取到 {len(response.data)} 个笔记本")
        return jsonify(response.data)
    except Exception as e:
        logger.error(f"获取笔记本列表失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 删除笔记本
@app.route('/api/notebooks/<notebook_id>', methods=['DELETE'])
@limiter.limit("30 per minute")
def delete_notebook(notebook_id):
    try:
        response = supabase.table('notebooks').delete().eq('id', notebook_id).execute()
        if not response.data:
            return jsonify({"error": "笔记本不存在"}), 404
        return jsonify(response.data[0])
    except Exception as e:
        logger.error(f"删除笔记本失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 创建卡片
@app.route('/api/cards', methods=['POST'])
@limiter.limit("20 per minute")
def create_card():
    data = request.json
    if not data or 'title' not in data or 'content' not in data or 'notebook_id' not in data:
        return jsonify({"error": "标题、内容和笔记本ID不能为空"}), 400
    
    try:
        # 计算下次复习时间（默认为24小时后）
        next_review = datetime.utcnow() + timedelta(hours=24)
        
        card_id = str(uuid.uuid4())
        response = supabase.table('cards').insert({
            "id": card_id,
            "notebook_id": data['notebook_id'],
            "title": data['title'],
            "content": data['content'],
            "next_review": next_review.isoformat(),
            "ease_factor": 2.5,
            "repetition": 0,
            "interval": 0
        }).execute()
        
        # 更新笔记本的卡片计数
        notebook = supabase.table('notebooks').select("card_count").eq('id', data['notebook_id']).execute()
        if notebook.data:
            current_count = notebook.data[0]['card_count']
            supabase.table('notebooks').update({"card_count": current_count + 1}).eq('id', data['notebook_id']).execute()
        
        return jsonify(response.data[0]), 201
    except Exception as e:
        logger.error(f"创建卡片失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 获取卡片列表
@app.route('/api/cards', methods=['GET'])
@limiter.limit("60 per minute")
def get_cards():
    notebook_id = request.args.get('notebook_id')
    review = request.args.get('review')
    
    try:
        logger.info(f"获取卡片列表: notebook_id={notebook_id}, review={review}")
        query = supabase.table('cards').select("*")
        
        # 如果指定了笔记本ID，则过滤指定笔记本的卡片
        if notebook_id:
            logger.info(f"过滤笔记本ID: {notebook_id}")
            query = query.eq('notebook_id', notebook_id)
            
        # 如果请求复习卡片，则只返回今天需要复习的卡片
        if review == 'true':
            now = datetime.utcnow().isoformat()
            logger.info(f"过滤复习卡片，当前时间: {now}")
            query = query.lte('next_review', now)
            
        response = query.execute()
        logger.info(f"获取到 {len(response.data)} 张卡片")
        
        # 详细记录每张卡片的信息
        for i, card in enumerate(response.data):
            logger.info(f"卡片 {i+1}: id={card.get('id')}, title={card.get('title')}, next_review={card.get('next_review')}")
            
        return jsonify(response.data)
    except Exception as e:
        logger.error(f"获取卡片列表失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 删除卡片
@app.route('/api/cards/<card_id>', methods=['DELETE'])
@limiter.limit("30 per minute")
def delete_card(card_id):
    try:
        # 获取卡片信息以获取notebook_id
        card = supabase.table('cards').select("notebook_id").eq('id', card_id).execute()
        if not card.data:
            return jsonify({"error": "卡片不存在"}), 404
            
        notebook_id = card.data[0]['notebook_id']
        
        # 删除卡片
        response = supabase.table('cards').delete().eq('id', card_id).execute()
        
        # 更新笔记本的卡片计数
        notebook = supabase.table('notebooks').select("card_count").eq('id', notebook_id).execute()
        if notebook.data:
            current_count = notebook.data[0]['card_count']
            supabase.table('notebooks').update({"card_count": max(0, current_count - 1)}).eq('id', notebook_id).execute()
        
        return jsonify(response.data[0])
    except Exception as e:
        logger.error(f"删除卡片失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 更新卡片
@app.route('/api/cards/<card_id>', methods=['PUT'])
@limiter.limit("30 per minute")
def update_card(card_id):
    data = request.json
    if not data:
        return jsonify({"error": "更新数据不能为空"}), 400
    
    try:
        # 获取当前卡片
        card = supabase.table('cards').select("*").eq('id', card_id).execute()
        if not card.data:
            return jsonify({"error": "卡片不存在"}), 404
        
        # 准备更新数据
        update_data = {}
        if 'title' in data:
            update_data['title'] = data['title']
        if 'content' in data:
            update_data['content'] = data['content']
        
        # 更新卡片
        response = supabase.table('cards').update(update_data).eq('id', card_id).execute()
        
        return jsonify(response.data[0])
    except Exception as e:
        logger.error(f"更新卡片失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 复习卡片
@app.route('/api/cards/<card_id>/review', methods=['POST'])
@limiter.limit("50 per minute")
def review_card(card_id):
    data = request.json
    if not data or 'quality' not in data:
        return jsonify({"error": "复习质量评分不能为空"}), 400
    
    try:
        logger.info(f"复习卡片: card_id={card_id}, quality={data['quality']}")
        # 获取当前卡片信息
        card = supabase.table('cards').select("*").eq('id', card_id).execute()
        if not card.data:
            return jsonify({"error": "卡片不存在"}), 404
            
        card_data = card.data[0]
        quality = int(data['quality'])  # 0-5的评分
        logger.info(f"当前卡片信息: repetition={card_data.get('repetition')}, interval={card_data.get('interval')}, ease_factor={card_data.get('ease_factor')}")
        
        # SM-2算法实现
        if quality >= 3:
            if card_data['repetition'] == 0:
                interval = 1
            elif card_data['repetition'] == 1:
                interval = 6
            else:
                interval = round(card_data['interval'] * card_data['ease_factor'])
            
            repetition = card_data['repetition'] + 1
            ease_factor = card_data['ease_factor'] + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))
            ease_factor = max(1.3, ease_factor)  # 确保ease_factor不小于1.3
        else:
            interval = 1
            repetition = 0
            ease_factor = max(1.3, card_data['ease_factor'] - 0.2)
            
        next_review = datetime.utcnow() + timedelta(days=interval)
        logger.info(f"更新后的卡片信息: repetition={repetition}, interval={interval}, ease_factor={ease_factor}, next_review={next_review.isoformat()}")
        
        # 更新卡片信息
        response = supabase.table('cards').update({
            "next_review": next_review.isoformat(),
            "ease_factor": ease_factor,
            "repetition": repetition,
            "interval": interval
        }).eq('id', card_id).execute()
        
        return jsonify(response.data[0])
    except Exception as e:
        logger.error(f"复习卡片失败: {str(e)}")
        return jsonify({"error": str(e)}), 500

# 润色内容
@app.route('/api/refine', methods=['POST'])
@limiter.limit("10 per minute")
def refine():
    data = request.json
    response = client.chat.completions.create(
        model='deepseek-ai/DeepSeek-V3',  # 硅基流动的模型名
        messages=data['messages']
    )
    return jsonify({'result': response.choices[0].message.content})

# 测试路由
@app.route('/api/test', methods=['GET'])
def test():
    return jsonify({"message": "API is working!"})

if __name__ == '__main__':
    logger.info("启动Flask服务器，端口5000")
    app.run(debug=True, port=5000) 